package com.sinodata.bsm.center.engine.resource.health;

import java.util.List;

import org.apache.log4j.Logger;

import com.sinodata.bsm.center.service.resource.ResHealthService;
import com.sinodata.bsm.center.util.spring.SpringContextHolder;
import com.sinodata.bsm.common.vo.*;
import com.sinodata.bsm.center.bean.RelationHelper;
import com.sinodata.bsm.center.bean.ResBean;

/**
 * 
 * <p>
 * 资源状态刷新的统一接口
 * </p>
 *
 * @author wangyilin
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * Jul 9, 2012 11:40:35 AM          wangyilin        1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class ResHealthEngine {
    private static Logger logger = Logger.getLogger(ResHealthEngine.class);
    private static ResHealthEngine instance = new ResHealthEngine();
    private static ResHealthService resHealthService = SpringContextHolder.getBean(ResHealthService.class);

    private ResHealthEngine() {
    }

    public static ResHealthEngine getInstance() {
        return instance;
    }

    /**
     * 刷新指定资源的状态(包括事件状态和健康度状态), 刷新方式为首先刷新该资源,后依次刷新至定级资源
     * (自下而上)
     * @param res
     */
    public synchronized void refreshResFromChild(Res res) {
        if (refreshRes(res))
            return;
        List<ResBean> parents = RelationHelper.parents(res.getId().longValue());
        for (ResBean bean : parents) {
            refreshResFromChild(bean.res());
        }
    }

    private boolean refreshRes(Res res) {
        int[] results = ResHealthCalculate.getResHealthStatus(res.getId().longValue());
        if (results[1] == res.getHealthStatus()) {
            return true;
        }
        resHealthService.updateResHealthStatus(res, results);
        return false;
    }

    public synchronized void refreshResFromParent(Res res) {
        refreshResFromParent(res, true);
    }

    /**
     * 刷新资源,如果isRoot为true表示是刷新的起始节点,当此节点状态变化时要继续刷新其父节点
     * @param resId
     * @param isRoot
     */
    private void refreshResFromParent(Res res, boolean isRoot) {
        List<ResBean> children = RelationHelper.children(res.getId().longValue());
        for (ResBean child : children) {
            refreshResFromParent(child.res(), false);
        }
        if (!refreshRes(res) && isRoot) {
            List<ResBean> parents = RelationHelper.parents(res.getId().longValue());
            for (ResBean bean : parents) {
                refreshResFromChild(bean.res());
            }
        }
    }

}
